// https://github.com/AlloyTeam/pasition

function shapeBox(shape) {
  let minX = shape[0][0],
    minY = shape[0][1],
    maxX = minX,
    maxY = minY;
  shape.forEach((curve) => {
    const x1 = curve[0],
      x2 = curve[2],
      x3 = curve[4],
      x4 = curve[6],
      y1 = curve[1],
      y2 = curve[3],
      y3 = curve[5],
      y4 = curve[7];

    minX = Math.min(minX, x1, x2, x3, x4);
    minY = Math.min(minY, y1, y2, y3, y4);
    maxX = Math.max(maxX, x1, x2, x3, x4);
    maxY = Math.max(maxY, y1, y2, y3, y4);
  });

  return [minX, minY, maxX, maxY];
}

function boxDistance(boxA, boxB) {
  return Math.sqrt((boxA[0] - boxB[0]) ** 2 + (boxA[1] - boxB[1]) ** 2)
    + Math.sqrt((boxA[2] - boxB[2]) ** 2 + (boxA[3] - boxB[3]) ** 2);
}

function curveDistance(curveA, curveB) {
  const x1 = curveA[0],
    x2 = curveA[2],
    x3 = curveA[4],
    x4 = curveA[6],
    y1 = curveA[1],
    y2 = curveA[3],
    y3 = curveA[5],
    y4 = curveA[7],

    xb1 = curveB[0],
    xb2 = curveB[2],
    xb3 = curveB[4],
    xb4 = curveB[6],
    yb1 = curveB[1],
    yb2 = curveB[3],
    yb3 = curveB[5],
    yb4 = curveB[7];

  return Math.sqrt((xb1 - x1) ** 2 + (yb1 - y1) ** 2)
        + Math.sqrt((xb2 - x2) ** 2 + (yb2 - y2) ** 2)
        + Math.sqrt((xb3 - x3) ** 2 + (yb3 - y3) ** 2)
        + Math.sqrt((xb4 - x4) ** 2 + (yb4 - y4) ** 2);
}

function sortCurves(curvesA, curvesB) {
  const arrList = permuteCurveNum(curvesA.length);

  const list = [];
  arrList.forEach((arr) => {
    let distance = 0;
    let i = 0;
    arr.forEach((index) => {
      distance += curveDistance(curvesA[index], curvesB[i++]);
    });
    list.push({index: arr, distance});
  });

  list.sort((a, b) => {
    return a.distance - b.distance;
  });

  const result = [];

  list[0].index.forEach((index) => {
    result.push(curvesA[index]);
  });

  return result;
}

function sort(pathA, pathB) {
  const arrList = permuteNum(pathA.length);

  const list = [];
  arrList.forEach((arr) => {
    let distance = 0;
    arr.forEach((index) => {
      distance += boxDistance(shapeBox(pathA[index]), shapeBox(pathB[index]));
    });
    list.push({index: arr, distance});
  });

  list.sort((a, b) => {
    return a.distance - b.distance;
  });

  const result = [];

  list[0].index.forEach((index) => {
    result.push(pathA[index]);
  });

  return result;
}

function permuteCurveNum(num) {
  const arr = [];

  for(let i = 0; i < num; i++) {
    const indexArr = [];
    for(let j = 0; j < num; j++) {
      let index = j + i;
      if(index > num - 1)index -= num;
      indexArr[index] = j;
    }

    arr.push(indexArr);
  }

  return arr;
}


function permuteNum(num) {
  const arr = [];
  for(let i = 0; i < num; i++) {
    arr.push(i);
  }

  return permute(arr);
}

function permute(input) {
  const permArr = [],
    usedChars = [];
  function main(input) {
    let i,
      ch;
    for(i = 0; i < input.length; i++) {
      ch = input.splice(i, 1)[0];
      usedChars.push(ch);
      if(input.length === 0) {
        permArr.push(usedChars.slice());
      }
      main(input);
      input.splice(i, 0, ch);
      usedChars.pop();
    }
    return permArr;
  }
  return main(input);
}

export {
  sort,
  sortCurves,
};